<?php

/**
 * This file is part of the Codizer package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright   Copyright (c) 2010 Advisa (http://www.advisa.fr)
 * @author      Codizer Core Team <team@codizer.org>
 * @package     Codizer
 */

class f_core_Context
{
	private static $instance;
	private $lang;
    private $frontLang;
    private $backLang;
    private $isBack = false;
	private $otherContexts;
	
	/**
	 * @return f_core_Context
	 */
	private function __construct()
	{
		$this->getCurrentLang();
		
		$session = f_core_Session::getInstance();
		
		$this->otherContexts = $session->getValue("contexts");
		
		return $this;
	}
	
	/**
	 * Get singleton instance
	 *
	 * @return f_core_Context
	 */
	public static function getInstance()
	{
		if(self::$instance === null)
		{
			self::$instance = new self();
		}
		return self::$instance;
	}
	
	/**
	 * @param string $value
	 * @return f_core_Context
	 */
	public function setLang($value)
	{
		$this->lang = $value;
		return $this;
	}

    /**
     * used to define a display lang in a back session
     *
     * @param string $lang
     * @return f_core_Context
     */
    public function setDisplayLang($displayLang)
    {
        $session = f_core_Session::getInstance();
        if($this->isBack)
        {
            $this->backLang = $displayLang;
            $session->setValue('backLang', $displayLang);
        }
        else
        {
            $this->frontLang = $displayLang;
        }
        return $this;
    }

    /**
     * Get available display langs from config file
     * @param boolean $back
     * @return array
     */
    public function getAvailableDisplayLangs($back = true)
    {
        $parameters = f_loader_Config::getInstance()->getParameters('default');
        
        if($back)
        {
            $langs = explode(',', $parameters['backLocale']);

            $result = array();
            foreach($langs as $lang)
            {
                $r = array();
                $r['id'] = $lang;
                $r['label'] = f_locale_Manager::getCultureLabel($lang);
                $result[] = $r;
            }

            return $result;
        }
        else
        {
            $langs = explode(',', $parameters['frontLocale']);

            $result = array();
            foreach($langs as $lang)
            {
                $r = array();
                $r['id'] = $lang;
                $r['label'] = f_locale_Manager::getCultureLabel($lang);
                $result[] = $r;
            }

            return $result;
        }
    }

    /**
     * Return current display lang
     * @return string
     */
    public function getDisplayLang()
    {        
        if($this->isBack)
        {
            if(is_null($this->backLang))
            {
                $session = f_core_Session::getInstance();
                $lang = $this->getBrowserLanguage(true);
                $this->backLang = $session->getValue('backLang', $lang);
            }
            return $this->backLang;
        }
        else
        {
            if(is_null($this->frontLang))
            {
                $session = f_core_Session::getInstance();
                $lang = $this->getBrowserLanguage();
                $this->frontLang = $session->getValue('frontLang', $lang);
            }
            return $this->frontLang;
        }
    }

    public function getBrowserLanguage()
    {
        if(CLI_MODE) return null;
        return substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
    }
	
	/**
	 * get setted context lang iso code
	 *
	 * @return string Lang iso code
	 */
	public function getLang()
	{		
		return $this->lang;
	}
	
	private function getCurrentLang()
	{
		$request = f_core_Request::getInstance();
				
		if($request->hasParameter('lang'))
		{
			$this->setLang(strtoupper($this->getRequestLang()));
		}
		else
		{
			$this->setLang(strtoupper($this->getDefaultLang()));
		}
	}
	
	/**
	 * Get lang iso code from request
	 *
	 * @return string Lang iso code
	 */
	public function getRequestLang()
	{		
		return strtolower(f_core_Request::getInstance()->getParameter("lang", $this->getDefaultLang()));
	}
	
	/**
	 * Get the default lang from config file
	 *
	 * @return string Lang iso code
	 */
	public function getDefaultLang()
	{
		$config = f_loader_Config::getInstance();
		
		$parameters = $config->getParameters("default");
		
		if(isset($parameters['defaultDocumentLang']))
		{
			return strtolower($parameters['defaultDocumentLang']);
		}
		
		throw new Exception("Default document lang is not set in config file");
	}

    public function beginBackSession($displayLang = null)
	{
        $this->isBack = true;
		return $this;
	}

    public function isBackSession()
    {
        return $this->isBack;
    }

    public function endBackSession()
	{
        $this->isBack = false;
	}
	
	/**
	 * Begin a work in another language
	 *
	 * @param string $lang
	 * @return f_core_Context
	 */
	public function beginI18nWork($lang)
	{
		$session = f_core_Session::getInstance();
		$session->setValue("i18nWorkLang", $this->getLang());
		$this->setLang(strtoupper($lang));
		return $this;
	}
	
	/**
	 * End work with another language
	 *
	 * @param mixed $e
	 */
	public function endI18nWork()
	{	
		$session = f_core_Session::getInstance();
		$this->setLang($session->getValue("i18nWorkLang"));
		$session->unsetValue("i18nWorkLang");
	}
	
	/**
	 * Add/modify a additional context
	 *
	 * @param string $contextName
	 * @param object|array|string|mixed $contextContent
	 */
	public function setContext($contextName, $contextContent)
	{
		$this->otherContexts[$contextName] = $contextContent;
		$session = f_core_Session::getInstance();		
		$session->setValue("contexts", $this->otherContexts);
	}
	
	/**
	 * Remove a context
	 *
	 * @param string $contextName
	 */
	public function removeContext($contextName)
	{
		unset($this->otherContexts[$contextName]);
		$session = f_core_Session::getInstance();
		$session->setValue("contexts", $this->otherContexts);
	}
	
	/**
	 * Check if a context exists
	 *
	 * @param string $contextName
	 * @return boolean
	 */
	public function contextExist($contextName)
	{
		return isset($this->otherContexts[$contextName]);
	}
	
	/**
	 * Retrieve context parameters
	 *
	 * @param string $contextName
	 * @return object|array|string|mixed|null
	 */
	public function getContext($contextName)
	{
		if($this->contextExist($contextName))
		{
			return $this->otherContexts[$contextName];
		}
		return null;
	}
}